package com.nulldev.util.gui.swingAPI.extensions;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.plaf.metal.MetalIconFactory;

import com.nulldev.util.data.Arrays.arrays.FastLists;

public class JTabbedPaneCloseButton extends JTabbedPane {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8322825947976585021L;
	public final List<CloseButtonTab> closeButtons = FastLists.list();

	public JTabbedPaneCloseButton() {
		super();
	}

	public JTabbedPaneCloseButton(final int val) {
		super(val);
	}

	public int tabs() {
		return this.closeButtons.size();
	}

	/* Override Addtab in order to add the close Button everytime */
	@Override
	public void addTab(String title, Icon icon, Component component, String tip) {
		super.addTab(title, icon, component, tip);
		int count = this.getTabCount() - 1;
		final CloseButtonTab c = new CloseButtonTab(component, title, icon);
		closeButtons.add(c);
		setTabComponentAt(count, c);
	}

	public CloseButtonTab addTabS(String title, Icon icon, Component component, String tip) {
		super.addTab(title, icon, component, tip);
		int count = this.getTabCount() - 1;
		final CloseButtonTab c = new CloseButtonTab(component, title, icon);
		closeButtons.add(c);
		setTabComponentAt(count, c);
		return c;
	}

	@Override
	public void addTab(String title, Icon icon, Component component) {
		addTab(title, icon, component, null);
	}

	@Override
	public void addTab(String title, Component component) {
		addTab(title, null, component);
	}

	public CloseButtonTab addTabS(String title, Icon icon, Component component) {
		return addTabS(title, icon, component, null);
	}

	public CloseButtonTab addTabS(String title, Component component) {
		return addTabS(title, null, component);
	}

	/* addTabNoExit */
	public void addTabNoExit(String title, Icon icon, Component component, String tip) {
		super.addTab(title, icon, component, tip);
	}

	public void addTabNoExit(String title, Icon icon, Component component) {
		addTabNoExit(title, icon, component, null);
	}

	public void addTabNoExit(String title, Component component) {
		addTabNoExit(title, null, component);
	}

	public void updateTitle(final String title, final int n) {
		final int f = n == 0 ? n : n - 1;
		// System.out.println("Update title '" + title + "' at '" + f + "'[" + n +
		// "].");
		this.closeButtons.get(f).setName(title);
	}

	// private BufferedImage img = ImageUtil.transparent(ix(), 0.5f);

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		// if (img != ImageUtil.transparent(ix(), 0.5f)) {
		// this.img = ImageUtil.transparent(ix(), 0.5f);
		// }
		// final int x = (getWidth() - img.getWidth()) / 2;
		// final int y = (getHeight() - img.getHeight()) / 2;
		// g.drawImage(this.img, x, y, img.getWidth(), img.getHeight(), this);
	}

	/* Button */
	public class CloseButtonTab extends JPanel {
		/**
		 * 
		 */
		private static final long serialVersionUID = -5989191921001535344L;
		private Component tab;
		private JButton button;
		private final LinkedList<Runnable> onClose = new LinkedList<Runnable>();

		public JLabel jLabel;
		private int id;

		public CloseButtonTab(final Component tab, String title, Icon icon) {
			this.tab = tab;
			this.id = closeButtons.size();
			setOpaque(false);
			FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 3, 3);
			setLayout(flowLayout);
			jLabel = new JLabel(title);
			jLabel.setIcon(icon);
			add(jLabel);

			try {
				// button = new JButton(new ImageIcon(ImageManager.exitScaled()));
				throw new IOException();
			} catch (IOException e) {
				button = new JButton(MetalIconFactory.getInternalFrameCloseIcon(8));
			} // MetalIconFactory.getInternalFrameCloseIcon(8));
			button.setMargin(new Insets(0, 0, 0, 0));
			button.addMouseListener(new CloseListener(tab) {
				public void ovrClose() {
					for (final Runnable close : CloseButtonTab.this.onClose) {
						close.run();
					}
				}
			});
//            jLabel.setBackground(prev.background());
//            jLabel.setForeground(prev.foreground());
//            setBackground(prev.background());
//            setForeground(prev.foreground());
			add(button);
		}

		public void enableTheming() {
			// ThemeApplier.applyTheme(this);
		}

		public int id() {
			return this.id;
		}

		@Override
		public void setName(String title) {
			super.setName(title);
			updateTitle(title);
		}

		public void updateTitle(String title) {
			jLabel.setText(title);
		}

		public Component getTab() {
			return this.tab;
		}

		public boolean registerCloseEvent(final Runnable r) {
			return this.onClose.add(r);
		}

		public void update() {
//            jLabel.setBackground(mode.background());
//            jLabel.setForeground(mode.foreground());
//            setBackground(mode.background());
//            setForeground(mode.foreground());
			// JTabbedPaneCloseButton.this.setBackgroundAt(this.id, mode.background());
		}

		public void setTitle(final String title) {
			if (title == null || this.jLabel == null) {
				return;
			}
			this.jLabel.setText(title);
		}

		public void runClose() {
			for (final Runnable close : CloseButtonTab.this.onClose) {
				close.run();
			}
		}
	}

	public void onClick(final MouseEvent e) {

	}

	/* ClickListener */
	public class CloseListener implements MouseListener {
		private Component tab;

		public CloseListener(Component tab) {
			this.tab = tab;
		}

		public void ovrClose() {
		}

		@Override
		public void mouseClicked(MouseEvent e) {
			if (e.getSource() instanceof JButton) {
				JButton clickedButton = (JButton) e.getSource();
				JTabbedPane tabbedPane = (JTabbedPane) clickedButton.getParent().getParent().getParent();
				tabbedPane.remove(tab);
				if (this.tab instanceof Closeable) {
					try {
						((Closeable) this.tab).close();
						this.ovrClose();
					} catch (IOException e1) {
					}
				}
				JTabbedPaneCloseButton.this.onClick(e);
			}
		}

		@Override
		public void mousePressed(MouseEvent e) {
		}

		@Override
		public void mouseReleased(MouseEvent e) {
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			if (e.getSource() instanceof JButton) {
				// JButton clickedButton = (JButton) e.getSource();
				// clickedButton.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY,3));
			}
		}

		@Override
		public void mouseExited(MouseEvent e) {
			if (e.getSource() instanceof JButton) {
				// JButton clickedButton = (JButton) e.getSource();
				// clickedButton.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY,3));
			}
		}
	}

	public List<CloseButtonTab> getTabs() {
		return this.closeButtons;
	}
}